const parties_list = [
  {
    "Name": "CDU",
    "comment": null,
    "highres":
      "https://de.wikipedia.org/wiki/Datei:CDU_flagge_logo_alternativ.svg",
    "preview":
      "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0e/CDU_Logo_2023.svg/330px-CDU_Logo_2023.svg.png",
    "color": "Black",
    "hex": "#000000",
  },
  {
    "Name": "AFD",
    "comment": " Duplicate of Alternative für Deutschland (Afd)",
    "highres":
      "https://upload.wikimedia.org/wikipedia/commons/b/b1/AfD_Logo_2021.svg?download",
    "preview":
      "https://upload.wikimedia.org/wikipedia/commons/thumb/4/48/AfD-Logo-2017.svg/240px-AfD-Logo-2017.svg.png",
    "color": "Dark Blue",
    "hex": "#003A70",
  },
  {
    "Name": "SPD",
    "comment": null,
    "highres": "https://de.wikipedia.org/wiki/Datei:SPD_Hessen.svg",
    "preview":
      "https://upload.wikimedia.org/wikipedia/de/thumb/c/ca/SPD_Hessen.svg/240px-SPD_Hessen.svg.png",
    "color": "Red",
    "hex": "#E3000F",
  },
  {
    "Name": "Bündnis 90/Die Grünen",
    "comment": null,
    "highres":
      "https://de.wikipedia.org/wiki/Datei:B%C3%BCndnis_90_Die_Gr%C3%BCnen.svg",
    "preview":
      "https://upload.wikimedia.org/wikipedia/de/thumb/1/16/B%C3%BCndnis_90_Die_Gr%C3%BCnen.svg/240px-B%C3%BCndnis_90_Die_Gr%C3%BCnen.svg.png",
    "color": "Green",
    "hex": "#00A950",
  },
  {
    "Name": "LINKE",
    "comment": null,
    "highres":
      "https://www.energie-klimaschutz.de/wp-content/uploads/2017/05/Die-Linke_DEZ_20170503.jpg",
    "preview":
      "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d6/Logo_Die_Linke_%282023%29.svg/450px-Logo_Die_Linke_%282023%29.svg.png",
    "color": "Maroon",
    "hex": "#A30000",
  },
  {
    "Name": "CSU",
    "comment": null,
    "highres": "https://de.wikipedia.org/wiki/Datei:CSU_Logo_since_2016.svg",
    "preview":
      "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ee/CSU_Logo_since_2016.svg/330px-CSU_Logo_since_2016.svg.png",
    "color": "Blue",
    "hex": "#007AC2",
  },
  {
    "Name": "FDP",
    "comment": null,
    "highres": "https://de.wikipedia.org/wiki/Datei:FDP_Sachsen-Anhalt.svg",
    "preview":
      "https://upload.wikimedia.org/wikipedia/de/thumb/e/e8/FDP_Sachsen-Anhalt.svg/240px-FDP_Sachsen-Anhalt.svg.png",
    "color": "Yellow",
    "hex": "#FFED00",
  },
  {
    "Name": "SSW",
    "comment": null,
    "highres":
      "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/S%C3%BCdschleswigscher_W%C3%A4hlerverband%2C_Logo.svg/500px-S%C3%BCdschleswigscher_W%C3%A4hlerverband%2C_Logo.svg.png",
    "preview":
      "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3a/S%C3%BCdschleswigscher_W%C3%A4hlerverband%2C_Logo.svg/640px-S%C3%BCdschleswigscher_W%C3%A4hlerverband%2C_Logo.svg.png?download",
    "color": "Yellow",
    "hex": "#FFD700",
  },
  {
    "Name": "BSW - Bündnis Sarah Wagenknecht",
    "comment": null,
    "highres":
      "https://de.wikipedia.org/wiki/Datei:B%C3%BCndnis_Sahra_Wagenknecht_logo_2.svg",
    "preview":
      "https://upload.wikimedia.org/wikipedia/commons/thumb/7/7f/B%C3%BCndnis_Sahra_Wagenknecht_logo_2.svg/450px-B%C3%BCndnis_Sahra_Wagenknecht_logo_2.svg.png",
    "color": "Deep Purple",
    "hex": "#660099",
  },
  {
    "Name": "Volt",
    "comment": null,
    "highres": "https://de.wikipedia.org/wiki/Datei:Logo_of_Volt.svg",
    "preview":
      "https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/Logo_of_Volt.svg/600px-Logo_of_Volt.svg.png",
    "color": "Purple",
    "hex": "#7F3FBF",
  },
  {
    "Name": "MLPD",
    "comment": null,
    "highres": "https://de.wikipedia.org/wiki/Datei:MLPD_Logo_2011_(2).svg",
    "preview":
      "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b1/MLPD_Logo_2011_%282%29.svg/300px-MLPD_Logo_2011_%282%29.svg.png",
    "color": "Red",
    "hex": "#FF0000",
  },
  {
    "Name": "DKP",
    "comment": null,
    "highres":
      "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Deutsche_Kommunistische_Partei_Logo.svg/500px-Deutsche_Kommunistische_Partei_Logo.svg.png",
    "preview":
      "https://upload.wikimedia.org/wikipedia/commons/thumb/c/c5/Deutsche_Kommunistische_Partei_Logo.svg/240px-Deutsche_Kommunistische_Partei_Logo.svg.png",
    "color": "Red",
    "hex": "#FF0000",
  },
  {
    "Name": "Team Todenhöfer",
    "comment": null,
    "highres":
      "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/Gerechtigkeitsparteilogo.png/500px-Gerechtigkeitsparteilogo.png",
    "preview":
      "https://upload.wikimedia.org/wikipedia/commons/thumb/d/d4/Gerechtigkeitsparteilogo.png/240px-Gerechtigkeitsparteilogo.png",
    "color": "Teal",
    "hex": "#008080",
  },
  {
    "Name": "Piraten",
    "comment": null,
    "highres": "https://de.wikipedia.org/wiki/Datei:Pidataratpartiet.svg",
    "preview":
      "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8c/Piratenpartei_deutschland_logo.svg/640px-Piratenpartei_deutschland_logo.svg.png?download",
    "color": "Purple",
    "hex": "#6600CC",
  },
  {
    "Name": "ÖDP",
    "comment": null,
    "highres":
      "https://upload.wikimedia.org/wikipedia/commons/thumb/3/3e/OEDP_Logo_CMYK.svg/300px-OEDP_Logo_CMYK.svg.png",
    "preview":
      "https://upload.wikimedia.org/wikipedia/commons/3/3e/OEDP_Logo_CMYK.svg",
    "color": "Green",
    "hex": "#008000",
  },
  {
    "Name": "PARTEI",
    "comment": null,
    "highres":
      "https://de.wikipedia.org/wiki/Datei:Die_PARTEI_Logo_Blur_Schatten_Vektor_V2.svg",
    "preview":
      "https://upload.wikimedia.org/wikipedia/commons/thumb/8/85/Die_PARTEI_Logo_Blur_Schatten_Vektor_V2.svg/640px-Die_PARTEI_Logo_Blur_Schatten_Vektor_V2.svg.png?download",
    "color": "Pink",
    "hex": "#FF69B4",
  },
  {
    "Name": "FW",
    "comment": null,
    "highres": "https://de.wikipedia.org/wiki/Datei:Freie_Waehler_Logo.svg",
    "preview":
      "https://upload.wikimedia.org/wikipedia/de/thumb/a/a6/Freie_Waehler_Logo.svg/240px-Freie_Waehler_Logo.svg.png",
    "color": "Orange",
    "hex": "#FF7F00",
  },
  {
    "Name": "Bayernpartei",
    "comment": null,
    "highres": null,
    "preview":
      "https://upload.wikimedia.org/wikipedia/commons/thumb/4/48/Bayernpartei_Logo.svg/270px-Bayernpartei_Logo.svg.png",
    "color": "Blue",
    "hex": "#0000FF",
  },
  {
    "Name": "Freie Wähler",
    "comment": null,
    "highres": "https://de.wikipedia.org/wiki/Datei:Freie_Waehler_Logo.svg",
    "preview":
      "https://upload.wikimedia.org/wikipedia/de/thumb/a/a6/Freie_Waehler_Logo.svg/240px-Freie_Waehler_Logo.svg.png",
    "color": "Orange",
    "hex": "#FF7F00",
  },
  {
    "Name": "NPD",
    "comment": "Umbenannt zu Heimat",
    "highres":
      "https://upload.wikimedia.org/wikipedia/commons/a/a2/Heimat-Logo.png",
    "preview":
      "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/Heimat-Logo.png/240px-Heimat-Logo.png",
    "color": "Dark Blue",
    "hex": "#00008B",
  },
  {
    "Name": "BVB/Freie Wähler",
    "comment": "Duplicate of “Freie Wähler”",
    "highres": null,
    "preview":
      "https://upload.wikimedia.org/wikipedia/de/thumb/a/a6/Freie_Waehler_Logo.svg/240px-Freie_Waehler_Logo.svg.png",
    "color": "Orange",
    "hex": "#FF7F00",
  },
  {
    "Name": "WerteUnion",
    "comment": null,
    "highres": "https://de.wikipedia.org/wiki/Datei:WerteUnion_Logo.svg",
    "preview":
      "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e2/WerteUnion_Logo.svg/640px-WerteUnion_Logo.svg.png",
    "color": "Dark Blue",
    "hex": "#00008B",
  },
];

const URI = "localhost";
const PORT = 7687;
const DEFAULT_YEAR_RANGE = [2021, 2025];
const DEFAULT_LIMIT = 250;

const NEO4J_CONFIG = {
  serverUrl: `bolt://${URI}:${PORT}`,
  serverUser: "neo4j",
  serverPassword: "lkjk3jlksfjlk34lkjrs432",
};

const BASE_CONFIG = {
  containerId: "viz",
  neo4j: NEO4J_CONFIG,
  labels: {
    visConfig: {
      nodes: {},
      edges: {
        length: 100,
        arrows: {
          to: { enabled: true },
        },
      },
      physics: {
        hierarchicalRepulsion: {
          avoidOverlap: 1,
        },
        solver: "repulsion",
        repulsion: {
          nodeDistance: 1500,
        },
      },
      layout: {
        improvedLayout: true,
        randomSeed: 420,
        hierarchical: {
          enabled: true,
          direction: "DU",
          sortMethod: "directed",
          nodeSpacing: 1000,
          treeSpacing: 20,
          levelSeparation: 250,
        },
      },
    },

    "Party": {
      label: "name",
      value: "pagerank",
      group: "community",
      [NeoVis.NEOVIS_ADVANCED_CONFIG]: {
        cypher: {
          value:
            "MATCH (n) WHERE id(n) = $id MATCH ()-[r]-(n) RETURN sum(r.amount) AS c",
        },
        function: {
          // color: (node) => ({
          //   background: node.properties.hex || "#CCCCCC",
          //   border: node.properties.hex || "#CCCCCC",
          // }),
          title: (props) =>
            NeoVis.objectToTitleHtml(props, ["name", "pagerank", "community"]),
          image: (node) => node.properties.preview,
        },
        static: {
          font: {
            size: 15,
            color: "#000000", // Font color
          },
          shape: "image", // Optional: specify shape
          size: 30, // Node size
        },
      },
    },
    "Person": {
      label: "name",
      value: "pagerank",
      group: "community",
      [NeoVis.NEOVIS_ADVANCED_CONFIG]: {
        cypher: {
          value:
            "MATCH (n) WHERE id(n) = $id MATCH (n)-[r]-() RETURN sum(r.amount) AS c",
        },
        function: {
          title: (props) =>
            NeoVis.objectToTitleHtml(props, ["name", "pagerank", "community"]),
        },
        static: {
          font: {
            size: 20,
            color: "#000000",
          },
          shape: "dot",
          // color: {
          //   background: "#33FF57",
          //   border: "#39C700",
          // },
          size: 25,
        },
      },
    },
    "Entity": {
      value: "pagerank",
      label: "name",
      group: "community",
      [NeoVis.NEOVIS_ADVANCED_CONFIG]: {
        cypher: {
          value:
            "MATCH (n) WHERE id(n) = $id MATCH (n)-[r]-() RETURN sum(r.amount) AS c",
        },
        function: {
          title: (props) =>
            NeoVis.objectToTitleHtml(props, ["name", "pagerank", "community"]),
        },
        static: {
          font: {
            size: 18,
            // color: "#000000",
          },
          shape: "dot",
          // color: {
          //   background: "#3357FF",
          //   border: "#0039C7",
          // },
          size: 20,
        },
      },
    },
  },
  relationships: {
    "DONATION": {
      value: "amount",
      group: "community",
      [NeoVis.NEOVIS_ADVANCED_CONFIG]: {
        function: {
          title: NeoVis.objectToTitleHtml,
        },
      },
    },
  },
};

// Alpine.js data store
document.addEventListener("alpine:init", () => {
  Alpine.store("filter", {
    parties: parties_list,
    donors: [""],
    yearRange: [DEFAULT_YEAR_RANGE[0], DEFAULT_YEAR_RANGE[1]],
    donorType: "all",
    strict: true,
    limit: DEFAULT_LIMIT,

    addDonorField() {
      this.donors.push("");
    },

    removeDonorField(index) {
      this.donors.splice(index, 1);
    },

    setDonorType(type) {
      this.donorType = type;
    },

    updateYearRange(start, end) {
      this.yearRange = [
        Math.min(parseInt(start), parseInt(end)),
        Math.max(parseInt(start), parseInt(end)),
      ];
    },
  });
});

class QueryBuilder {
  buildQuery(params = {}) {
    const {
      parties = [],
      donors = [],
      yearRange = DEFAULT_YEAR_RANGE,
      strict = true,
      donorType = "all",
      limit = DEFAULT_LIMIT,
    } = params;

    let donorMatch = "(n)";
    if (donorType === "person") {
      donorMatch = "(n:Person)";
    } else if (donorType === "entity") {
      donorMatch = "(n:Entity)";
    }

    const whereConditions = [];

    // Add party conditions only if not all parties are selected
    if (parties.length > 0 && parties.length < parties_list.length) {
      const partyCondition = parties.map((p) => `m.name = '${p}'`).join(" OR ");
      whereConditions.push(`(${partyCondition})`);
    }

    // Add donor name conditions
    if (donors.length > 0) {
      const validDonors = donors.filter(Boolean);
      if (validDonors.length > 0) {
        const donorCondition = validDonors.map((d) => `n.name CONTAINS '${d}'`)
          .join(" OR ");
        whereConditions.push(`(${donorCondition})`);
      }
    }

    // Add year range condition - always included and connected with AND
    const yearCondition = `(r.year >= ${yearRange[0]} AND r.year <= ${
      yearRange[1]
    })`;

    // Build WHERE clause
    let whereClause = "";
    if (whereConditions.length > 0) {
      const otherConditions = whereConditions.join(strict ? " AND " : " OR ");
      whereClause = `WHERE (${otherConditions}) AND ${yearCondition}`;
    } else {
      whereClause = `WHERE ${yearCondition}`;
    }

    return `
      MATCH ${donorMatch}-[r:DONATION]->(m:Party)
      ${whereClause}
      RETURN n, r, m
      ORDER BY r.amount DESC
      LIMIT ${limit}
    `.trim();
  }
}

// UI State Management
let viz;
const queryBuilder = new QueryBuilder();

function initializeVisualization() {
  viz = new NeoVis.default({
    ...BASE_CONFIG,
    initialCypher: queryBuilder.buildQuery(),
  });
  viz.render();
}

// UI State Management
function updateVisualization(reset = true) {
  const filterState = Alpine.store("filter");
  const query = queryBuilder.buildQuery({
    parties: filterState.parties,
    donors: filterState.donors.filter(Boolean),
    yearRange: filterState.yearRange,
    strict: filterState.strict,
    donorType: filterState.donorType,
    limit: filterState.limit,
  });

  if (reset) {
    viz.clearNetwork();
  }
  viz.updateWithCypher(query);
  console.log("Query", query, reset);
}

// Initialize application
document.addEventListener("DOMContentLoaded", async () => {
  // Observe explainer visibility
  const explainer = document.getElementById("explainer");
  const toggleButton = document.getElementById("toggleSidebar");
  const sidebar = document.getElementById("sidebar");

  initializeVisualization();
  initializePartySelect();

  // Event listeners for filter changes
  Alpine.effect(() => {
    // Check for saved state
    const savedState = localStorage.getItem("visualizationState");
    if (savedState) {
      // Show explainer when there is no state
      document.getElementById("explainer").classList.add("translate-x-full");
    }

    // Save State
    const state = Alpine.store("filter");
    localStorage.setItem("visualizationState", JSON.stringify(state));

    // Track previous state for comparison
    const prevState = JSON.parse(localStorage.getItem("previousState") || "{}");

    // Determine if we need to reset based on certain changes
    const shouldReset = !prevState.parties ||
      // state.parties != prevState.parties || // Part Changes
      !prevState.parties.every((party) => state.parties.includes(party)) || // Do not reset if a party was added
      state.parties.length < prevState.parties.length || // Party unselected
      state.donors.length < prevState.donors.length || // Donor removed
      state.donorType !== prevState.donorType; // Donor type changed

    updateVisualization(shouldReset);

    // Save current state as previous state
    localStorage.setItem("previousState", JSON.stringify(state));
  });

  // Toggle sidebar functionality
  toggleButton.addEventListener("click", () => {
    sidebar.classList.toggle("hidden");
  });

  // Event listeners for non-Alpine elements
  document.getElementById("toggleSidebar").addEventListener("click", () => {
    document.getElementById("sidebar").classList.toggle("hidden");
  });

  const observer = new MutationObserver((mutations) => {
    mutations.forEach((mutation) => {
      if (mutation.target.classList.contains("translate-x-full")) {
        toggleButton.style.display = "block";
      } else {
        toggleButton.style.display = "none";
      }
    });
  });

  observer.observe(explainer, { attributes: true, attributeFilter: ["class"] });
});

// Initialize event listeners
document.getElementById("toggleSidebar").addEventListener("click", () => {
  document.getElementById("sidebar").classList.toggle("hidden");
});

// TODO add tutorial
// document.getElementById('startTutorial').addEventListener('click', startTutorial);

// Fix hamburger visibility when explainer is open
const explainer = document.getElementById("explainer");
const toggleButton = document.getElementById("toggleSidebar");

const observer = new MutationObserver((mutations) => {
  mutations.forEach((mutation) => {
    if (mutation.target.classList.contains("translate-x-full")) {
      toggleButton.style.display = "block";
    } else {
      toggleButton.style.display = "none";
    }
  });
});

observer.observe(explainer, { attributes: true, attributeFilter: ["class"] });

// Fix filter positioning
const sidebar = document.getElementById("sidebar");
sidebar.style.top = "30px"; // Add space for the hamburger

// Make explainer scrollable
explainer.style.overflowY = "auto";

// Initialize party select dropdown
function initializePartySelect() {
  const select = document.getElementById("partySelect");
  parties_list.forEach((party) => {
    // console.log(party);
    const option = document.createElement("option");
    option.value = party.Name;

    // Check if the party has a logo
    if (party.preview) {
      option.innerHTML = `
        <div class="party-option flex items-center">
          <img src="${party.preview}" alt="${party.Name}" width="20" height="20" class="mr-2">
          <span>${party.Name}</span>
        </div>
      `;
    } else {
      option.innerHTML = `
        <div class="party-option">
          <span>${party.Name}</span>
        </div>
      `;
    }

    // option.style.backgroundColor = party.hex;
    select.appendChild(option);
  });
}

// FIXME add Tutorial
// // Tutorial steps
// const tutorialSteps = [
//   {
//     title: "Einzelne Partei",
//     config: {
//       parties: ["Bündnis 90/Die Grünen"],
//       donors: [],
//       strict: false
//     },
//     description: "Hier sehen Sie alle Spenden an die Grünen."
//   },
//   {
//     title: "Ampel Parteien",
//     config: {
//       parties: ["Bündnis 90/Die Grünen", "FDP", "SPD"],
//       donors: [],
//       strict: false
//     },
//     description: "Spenden an die Ampel-Koalition im Vergleich."
//   },
//   {
//     title: "Verundete Suche",
//     config: {
//       parties: ["CDU", "AFD"],
//       donors: [],
//       strict: true
//     },
//     description: "Spender, die sowohl an CDU als auch AFD gespendet haben."
//   }
// ];
//
// let currentTutorialStep = 0;
//
// function startTutorial() {
//   showTutorialStep(0);
// }
//
// function showTutorialStep(step) {
//   if (step >= tutorialSteps.length) {
//     endTutorial();
//     return;
//   }
//
//   const tutorialConfig = tutorialSteps[step];
//   // TODO Update UI with tutorial configuration
//   // ... implementation details ...
//   updateVisualization();
// }

// Function below are used in the html part
// Show/Hide Explainer
function toggleExplainer() {
  const explainer = document.getElementById("explainer");
  explainer.classList.toggle("translate-x-full");
}

function closeExplainer() {
  document.getElementById("explainer").classList.add("translate-x-full");
  localStorage.setItem("explainerSeen", "true");
}

// Show/Hide Legend
function toggleLegend() {
  const legend = document.getElementById("legend");
  legend.classList.toggle("hidden");
}
function toggleZeitraumInfo() {
  const zeitraumInfo = document.getElementById("zeitraum-info");
  zeitraumInfo.classList.toggle("hidden");
}
